home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************
- Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
- The Netherlands.
-
- All Rights Reserved
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the names of Stichting Mathematisch
- Centrum or CWI or Corporation for National Research Initiatives or
- CNRI not be used in advertising or publicity pertaining to
- distribution of the software without specific, written prior
- permission.
-
- While CWI is the initial source for this software, a modified version
- is made available by the Corporation for National Research Initiatives
- (CNRI) at the Internet address ftp://ftp.python.org.
-
- STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
- REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
- CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-
- ******************************************************************/
-
- /* List object implementation */
-
- #include "Python.h"
-
- #ifdef STDC_HEADERS
- #include <stddef.h>
- #else
- #include <sys/types.h> /* For size_t */
- #endif
-
- #include "protos/listobject_protos.h"
-
- #define ROUNDUP(n, PyTryBlock) \
- ((((n)+(PyTryBlock)-1)/(PyTryBlock))*(PyTryBlock))
-
- static int
- roundupsize(n)
- int n;
- {
- if (n < 500)
- return ROUNDUP(n, 10);
- else
- return ROUNDUP(n, 100);
- }
-
- #define NRESIZE(var, type, nitems) PyMem_RESIZE(var, type, roundupsize(nitems))
-
- PyObject *
- PyList_New(size)
- int size;
- {
- int i;
- PyListObject *op;
- size_t nbytes;
- if (size < 0) {
- PyErr_BadInternalCall();
- return NULL;
- }
- nbytes = size * sizeof(PyObject *);
- /* Check for overflow */
- if (nbytes / sizeof(PyObject *) != (size_t)size) {
- return PyErr_NoMemory();
- }
- op = (PyListObject *) malloc(sizeof(PyListObject));
- if (op == NULL) {
- return PyErr_NoMemory();
- }
- if (size <= 0) {
- op->ob_item = NULL;
- }
- else {
- op->ob_item = (PyObject **) malloc(nbytes);
- if (op->ob_item == NULL) {
- free((ANY *)op);
- return PyErr_NoMemory();
- }
- }
- op->ob_type = &PyList_Type;
- op->ob_size = size;
- for (i = 0; i < size; i++)
- op->ob_item[i] = NULL;
- _Py_NewReference(op);
- return (PyObject *) op;
- }
-
- int
- PyList_Size(op)
- PyObject *op;
- {
- if (!PyList_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
- else
- return ((PyListObject *)op) -> ob_size;
- }
-
- static PyObject *indexerr;
-
- PyObject *
- PyList_GetItem(op, i)
- PyObject *op;
- int i;
- {
- if (!PyList_Check(op)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- if (i < 0 || i >= ((PyListObject *)op) -> ob_size) {
- if (indexerr == NULL)
- indexerr = PyString_FromString(
- "list index out of range");
- PyErr_SetObject(PyExc_IndexError, indexerr);
- return NULL;
- }
- return ((PyListObject *)op) -> ob_item[i];
- }
-
- int
- PyList_SetItem(op, i, newitem)
- register PyObject *op;
- register int i;
- register PyObject *newitem;
- {
- register PyObject *olditem;
- register PyObject **p;
- if (!PyList_Check(op)) {
- Py_XDECREF(newitem);
- PyErr_BadInternalCall();
- return -1;
- }
- if (i < 0 || i >= ((PyListObject *)op) -> ob_size) {
- Py_XDECREF(newitem);
- PyErr_SetString(PyExc_IndexError,
- "list assignment index out of range");
- return -1;
- }
- p = ((PyListObject *)op) -> ob_item + i;
- olditem = *p;
- *p = newitem;
- Py_XDECREF(olditem);
- return 0;
- }
-
- static int
- ins1(self, where, v)
- PyListObject *self;
- int where;
- PyObject *v;
- {
- int i;
- PyObject **items;
- if (v == NULL) {
- PyErr_BadInternalCall();
- return -1;
- }
- items = self->ob_item;
- NRESIZE(items, PyObject *, self->ob_size+1);
- if (items == NULL) {
- PyErr_NoMemory();
- return -1;
- }
- if (where < 0)
- where = 0;
- if (where > self->ob_size)
- where = self->ob_size;
- for (i = self->ob_size; --i >= where; )
- items[i+1] = items[i];
- Py_INCREF(v);
- items[where] = v;
- self->ob_item = items;
- self->ob_size++;
- return 0;
- }
-
- int
- PyList_Insert(op, where, newitem)
- PyObject *op;
- int where;
- PyObject *newitem;
- {
- if (!PyList_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return ins1((PyListObject *)op, where, newitem);
- }
-
- int
- PyList_Append(op, newitem)
- PyObject *op;
- PyObject *newitem;
- {
- if (!PyList_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return ins1((PyListObject *)op,
- (int) ((PyListObject *)op)->ob_size, newitem);
- }
-
- /* Methods */
-
- static void
- list_dealloc(op)
- PyListObject *op;
- {
- int i;
- if (op->ob_item != NULL) {
- for (i = 0; i < op->ob_size; i++) {
- Py_XDECREF(op->ob_item[i]);
- }
- free((ANY *)op->ob_item);
- }
- free((ANY *)op);
- }
-
- static int
- list_print(op, fp, flags)
- PyListObject *op;
- FILE *fp;
- int flags;
- {
- int i;
-
- i = Py_ReprEnter((PyObject*)op);
- if (i != 0) {
- if (i < 0)
- return i;
- fprintf(fp, "[...]");
- return 0;
- }
- fprintf(fp, "[");
- for (i = 0; i < op->ob_size; i++) {
- if (i > 0)
- fprintf(fp, ", ");
- if (PyObject_Print(op->ob_item[i], fp, 0) != 0) {
- Py_ReprLeave((PyObject *)op);
- return -1;
- }
- }
- fprintf(fp, "]");
- Py_ReprLeave((PyObject *)op);
- return 0;
- }
-
- static PyObject *
- list_repr(v)
- PyListObject *v;
- {
- PyObject *s, *comma;
- int i;
-
- i = Py_ReprEnter((PyObject*)v);
- if (i != 0) {
- if (i > 0)
- return PyString_FromString("[...]");
- return NULL;
- }
- s = PyString_FromString("[");
- comma = PyString_FromString(", ");
- for (i = 0; i < v->ob_size && s != NULL; i++) {
- if (i > 0)
- PyString_Concat(&s, comma);
- PyString_ConcatAndDel(&s, PyObject_Repr(v->ob_item[i]));
- }
- Py_XDECREF(comma);
- PyString_ConcatAndDel(&s, PyString_FromString("]"));
- Py_ReprLeave((PyObject *)v);
- return s;
- }
-
- static int
- list_compare(v, w)
- PyListObject *v, *w;
- {
- int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
- int i;
- for (i = 0; i < len; i++) {
- int cmp = PyObject_Compare(v->ob_item[i], w->ob_item[i]);
- if (cmp != 0)
- return cmp;
- }
- return v->ob_size - w->ob_size;
- }
-
- static int
- list_length(a)
- PyListObject *a;
- {
- return a->ob_size;
- }
-
- static PyObject *
- list_item(a, i)
- PyListObject *a;
- int i;
- {
- if (i < 0 || i >= a->ob_size) {
- if (indexerr == NULL)
- indexerr = PyString_FromString(
- "list index out of range");
- PyErr_SetObject(PyExc_IndexError, indexerr);
- return NULL;
- }
- Py_INCREF(a->ob_item[i]);
- return a->ob_item[i];
- }
-
- static PyObject *
- list_slice(a, ilow, ihigh)
- PyListObject *a;
- int ilow, ihigh;
- {
- PyListObject *np;
- int i;
- if (ilow < 0)
- ilow = 0;
- else if (ilow > a->ob_size)
- ilow = a->ob_size;
- if (ihigh < 0)
- ihigh = 0;
- if (ihigh < ilow)
- ihigh = ilow;
- else if (ihigh > a->ob_size)
- ihigh = a->ob_size;
- np = (PyListObject *) PyList_New(ihigh - ilow);
- if (np == NULL)
- return NULL;
- for (i = ilow; i < ihigh; i++) {
- PyObject *v = a->ob_item[i];
- Py_INCREF(v);
- np->ob_item[i - ilow] = v;
- }
- return (PyObject *)np;
- }
-
- PyObject *
- PyList_GetSlice(a, ilow, ihigh)
- PyObject *a;
- int ilow, ihigh;
- {
- if (!PyList_Check(a)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return list_slice((PyListObject *)a, ilow, ihigh);
- }
-
- static PyObject *
- list_concat(a, bb)
- PyListObject *a;
- PyObject *bb;
- {
- int size;
- int i;
- PyListObject *np;
- if (!PyList_Check(bb)) {
- PyErr_BadArgument();
- return NULL;
- }
- #define b ((PyListObject *)bb)
- size = a->ob_size + b->ob_size;
- np = (PyListObject *) PyList_New(size);
- if (np == NULL) {
- return NULL;
- }
- for (i = 0; i < a->ob_size; i++) {
- PyObject *v = a->ob_item[i];
- Py_INCREF(v);
- np->ob_item[i] = v;
- }
- for (i = 0; i < b->ob_size; i++) {
- PyObject *v = b->ob_item[i];
- Py_INCREF(v);
- np->ob_item[i + a->ob_size] = v;
- }
- return (PyObject *)np;
- #undef b
- }
-
- static PyObject *
- list_repeat(a, n)
- PyListObject *a;
- int n;
- {
- int i, j;
- int size;
- PyListObject *np;
- PyObject **p;
- if (n < 0)
- n = 0;
- size = a->ob_size * n;
- np = (PyListObject *) PyList_New(size);
- if (np == NULL)
- return NULL;
- p = np->ob_item;
- for (i = 0; i < n; i++) {
- for (j = 0; j < a->ob_size; j++) {
- *p = a->ob_item[j];
- Py_INCREF(*p);
- p++;
- }
- }
- return (PyObject *) np;
- }
-
- static int
- list_ass_slice(a, ilow, ihigh, v)
- PyListObject *a;
- int ilow, ihigh;
- PyObject *v;
- {
- /* Because [X]DECREF can recursively invoke list operations on
- this list, we must postpone all [X]DECREF activity until
- after the list is back in its canonical shape. Therefore
- we must allocate an additional array, 'recycle', into which
- we temporarily copy the items that are deleted from the
- list. :-( */
- PyObject **recycle, **p;
- PyObject **item;
- int n; /* Size of replacement list */
- int d; /* Change in size */
- int k; /* Loop index */
- #define b ((PyListObject *)v)
- if (v == NULL)
- n = 0;
- else if (PyList_Check(v)) {
- n = b->ob_size;
- if (a == b) {
- /* Special case "a[i:j] = a" -- copy b first */
- int ret;
- v = list_slice(b, 0, n);
- ret = list_ass_slice(a, ilow, ihigh, v);
- Py_DECREF(v);
- return ret;
- }
- }
- else {
- PyErr_BadArgument();
- return -1;
- }
- if (ilow < 0)
- ilow = 0;
- else if (ilow > a->ob_size)
- ilow = a->ob_size;
- if (ihigh < 0)
- ihigh = 0;
- if (ihigh < ilow)
- ihigh = ilow;
- else if (ihigh > a->ob_size)
- ihigh = a->ob_size;
- item = a->ob_item;
- d = n - (ihigh-ilow);
- if (ihigh > ilow)
- p = recycle = PyMem_NEW(PyObject *, (ihigh-ilow));
- else
- p = recycle = NULL;
- if (d <= 0) { /* Delete -d items; recycle ihigh-ilow items */
- for (k = ilow; k < ihigh; k++)
- *p++ = item[k];
- if (d < 0) {
- for (/*k = ihigh*/; k < a->ob_size; k++)
- item[k+d] = item[k];
- a->ob_size += d;
- NRESIZE(item, PyObject *, a->ob_size); /* Can't fail */
- a->ob_item = item;
- }
- }
- else { /* Insert d items; recycle ihigh-ilow items */
- NRESIZE(item, PyObject *, a->ob_size + d);
- if (item == NULL) {
- PyMem_XDEL(recycle);
- PyErr_NoMemory();
- return -1;
- }
- for (k = a->ob_size; --k >= ihigh; )
- item[k+d] = item[k];
- for (/*k = ihigh-1*/; k >= ilow; --k)
- *p++ = item[k];
- a->ob_item = item;
- a->ob_size += d;
- }
- for (k = 0; k < n; k++, ilow++) {
- PyObject *w = b->ob_item[k];
- Py_XINCREF(w);
- item[ilow] = w;
- }
- if (recycle) {
- while (--p >= recycle)
- Py_XDECREF(*p);
- PyMem_DEL(recycle);
- }
- return 0;
- #undef b
- }
-
- int
- PyList_SetSlice(a, ilow, ihigh, v)
- PyObject *a;
- int ilow, ihigh;
- PyObject *v;
- {
- if (!PyList_Check(a)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return list_ass_slice((PyListObject *)a, ilow, ihigh, v);
- }
-
- static int
- list_ass_item(a, i, v)
- PyListObject *a;
- int i;
- PyObject *v;
- {
- PyObject *old_value;
- if (i < 0 || i >= a->ob_size) {
- PyErr_SetString(PyExc_IndexError,
- "list assignment index out of range");
- return -1;
- }
- if (v == NULL)
- return list_ass_slice(a, i, i+1, v);
- Py_INCREF(v);
- old_value = a->ob_item[i];
- a->ob_item[i] = v;
- Py_DECREF(old_value);
- return 0;
- }
-
- static PyObject *
- ins(self, where, v)
- PyListObject *self;
- int where;
- PyObject *v;
- {
- if (ins1(self, where, v) != 0)
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- static PyObject *
- listinsert(self, args)
- PyListObject *self;
- PyObject *args;
- {
- int i;
- PyObject *v;
- if (!PyArg_Parse(args, "(iO)", &i, &v))
- return NULL;
- return ins(self, i, v);
- }
-
- static PyObject *
- listappend(self, args)
- PyListObject *self;
- PyObject *args;
- {
- PyObject *v;
- if (!PyArg_Parse(args, "O", &v))
- return NULL;
- return ins(self, (int) self->ob_size, v);
- }
-
- #define NEWSORT
-
- #ifdef NEWSORT
-
- /* New quicksort implementation for arrays of object pointers.
- Thanks to discussions with Tim Peters. */
-
- /* CMPERROR is returned by our comparison function when an error
- occurred. This is the largest negative integer (0x80000000 on a
- 32-bit system). */
- #define CMPERROR ( (int) ((unsigned int)1 << (8*sizeof(int) - 1)) )
-
- /* Comparison function. Takes care of calling a user-supplied
- comparison function (any callable Python object). Calls the
- standard comparison function, cmpobject(), if the user-supplied
- function is NULL. */
-
- static int
- docompare(x, y, compare)
- PyObject *x;
- PyObject *y;
- PyObject *compare;
- {
- PyObject *args, *res;
- int i;
-
- if (compare == NULL) {
- i = PyObject_Compare(x, y);
- if (i && PyErr_Occurred())
- i = CMPERROR;
- return i;
- }
-
- args = Py_BuildValue("(OO)", x, y);
- if (args == NULL)
- return CMPERROR;
- res = PyEval_CallObject(compare, args);
- Py_DECREF(args);
- if (res == NULL)
- return CMPERROR;
- if (!PyInt_Check(res)) {
- Py_DECREF(res);
- PyErr_SetString(PyExc_TypeError,
- "comparison function should return int");
- return CMPERROR;
- }
- i = PyInt_AsLong(res);
- Py_DECREF(res);
- if (i < 0)
- return -1;
- if (i > 0)
- return 1;
- return 0;
- }
-
- /* Straight insertion sort. More efficient for sorting small arrays. */
-
- static int
- insertionsort(array, size, compare)
- PyObject **array; /* Start of array to sort */
- int size; /* Number of elements to sort */
- PyObject *compare;/* Comparison function object, or NULL for default */
- {
- register PyObject **a = array;
- register PyObject **end = array+size;
- register PyObject **p;
-
- for (p = a+1; p < end; p++) {
- register PyObject *key = *p;
- register PyObject **q = p;
- while (--q >= a) {
- register int k = docompare(*q, key, compare);
- if (k == CMPERROR)
- return -1;
- if (k <= 0)
- break;
- *(q+1) = *q;
- *q = key; /* For consistency */
- }
- }
-
- return 0;
- }
-
- /* MINSIZE is the smallest array we care to partition; smaller arrays
- are sorted using a straight insertion sort (above). It must be at
- least 2 for the quicksort implementation to work. Assuming that
- comparisons are more expensive than everything else (and this is a
- good assumption for Python), it should be 10, which is the cutoff
- point: quicksort requires more comparisons than insertion sort for
- smaller arrays. */
- #define MINSIZE 10
-
- /* STACKSIZE is the size of our work stack. A rough estimate is that
- this allows us to sort arrays of MINSIZE * 2**STACKSIZE, or large
- enough. (Because of the way we push the biggest partition first,
- the worst case occurs when all subarrays are always partitioned
- exactly in two.) */
- #define STACKSIZE 64
-
- /* Quicksort algorithm. Return -1 if an exception occurred; in this
- case we leave the array partly sorted but otherwise in good health
- (i.e. no items have been removed or duplicated). */
-
- static int
- quicksort(array, size, compare)
- PyObject **array; /* Start of array to sort */
- int size; /* Number of elements to sort */
- PyObject *compare;/* Comparison function object, or NULL for default */
- {
- register PyObject *tmp, *pivot;
- register PyObject **lo, **hi, **l, **r;
- int top, k, n, n2;
- PyObject **lostack[STACKSIZE];
- PyObject **histack[STACKSIZE];
-
- /* Start out with the whole array on the work stack */
- lostack[0] = array;
- histack[0] = array+size;
- top = 1;
-
- /* Repeat until the work stack is empty */
- while (--top >= 0) {
- lo = lostack[top];
- hi = histack[top];
-
- /* If it's a small one, use straight insertion sort */
- n = hi - lo;
- if (n < MINSIZE) {
- /*
- * skip it. The insertion sort at the end will
- * catch these
- */
- continue;
- }
-
- /* Choose median of first, middle and last item as pivot */
-
- l = lo + (n>>1); /* Middle */
- r = hi - 1; /* Last */
-
- k = docompare(*l, *lo, compare);
- if (k == CMPERROR)
- return -1;
- if (k < 0)
- { tmp = *lo; *lo = *l; *l = tmp; }
-
- k = docompare(*r, *l, compare);
- if (k == CMPERROR)
- return -1;
- if (k < 0)
- { tmp = *r; *r = *l; *l = tmp; }
-
- k = docompare(*l, *lo, compare);
- if (k == CMPERROR)
- return -1;
- if (k < 0)
- { tmp = *l; *l = *lo; *lo = tmp; }
- pivot = *l;
-
- /* Partition the array */
- l = lo+1;
- r = hi-2;
- for (;;) {
- /* Move left index to element > pivot */
- while (l < hi) {
- k = docompare(*l, pivot, compare);
- if (k == CMPERROR)
- return -1;
- if (k >= 0)
- break;
- l++;
- }
- /* Move right index to element < pivot */
- while (r >= lo) {
- k = docompare(pivot, *r, compare);
- if (k == CMPERROR)
- return -1;
- if (k >= 0)
- break;
- r--;
- }
-
- /* If they met, we're through */
- if (l < r) {
- /* Swap elements and continue */
- tmp = *l; *l = *r; *r = tmp;
- l++; r--;
- }
- else if (l == r) {
- l++; r--;
- break;
- }
-
- if (l > r)
- break;
- }
-
-
- /* We have now reached the following conditions:
- lo <= r < l <= hi
- all x in [lo,r) are <= pivot
- all x in [r,l) are == pivot
- all x in [l,hi) are >= pivot
- The partitions are [lo,r) and [l,hi)
- */
-
- /* Push biggest partition first */
- n = r - lo;
- n2 = hi - l;
- if (n > n2) {
- /* First one is bigger */
- if (n > MINSIZE) {
- lostack[top] = lo;
- histack[top++] = r;
- if (n2 > MINSIZE) {
- lostack[top] = l;
- histack[top++] = hi;
- }
- }
- } else {
- /* Second one is bigger */
- if (n2 > MINSIZE) {
- lostack[top] = l;
- histack[top++] = hi;
- if (n > MINSIZE) {
- lostack[top] = lo;
- histack[top++] = r;
- }
- }
- }
-
- /* Should assert top < STACKSIZE-1 */
- }
-
- /*
- * Ouch - even if I screwed up the quicksort above, the
- * insertionsort below will cover up the problem - just a
- * performance hit would be noticable.
- */
-
- /* insertionsort is pretty fast on the partially sorted list */
-
- if (insertionsort(array, size, compare) < 0)
- return -1;
-
- /* Succes */
- return 0;
- }
-
- static PyObject *
- listsort(self, compare)
- PyListObject *self;
- PyObject *compare;
- {
- /* XXX Don't you *dare* changing the list's length in compare()! */
- if (quicksort(self->ob_item, self->ob_size, compare) < 0)
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- #else /* !NEWSORT */
-
- static PyObject *comparefunc;
-
- static int
- cmp(v, w)
- const ANY *v, *w;
- {
- PyObject *t, *res;
- long i;
-
- if (PyErr_Occurred())
- return 0;
-
- if (comparefunc == NULL)
- return PyObject_Compare(* (PyObject **) v, * (PyObject **) w);
-
- /* Call the user-supplied comparison function */
- t = Py_BuildValue("(OO)", * (PyObject **) v, * (PyObject **) w);
- if (t == NULL)
- return 0;
- res = PyEval_CallObject(comparefunc, t);
- Py_DECREF(t);
- if (res == NULL)
- return 0;
- if (!PyInt_Check(res)) {
- PyErr_SetString(PyExc_TypeError,
- "comparison function should return int");
- i = 0;
- }
- else {
- i = PyInt_AsLong(res);
- if (i < 0)
- i = -1;
- else if (i > 0)
- i = 1;
- }
- Py_DECREF(res);
- return (int) i;
- }
-
- static PyObject *
- listsort(self, args)
- PyListObject *self;
- PyObject *args;
- {
- PyObject *save_comparefunc;
- if (self->ob_size <= 1) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- save_comparefunc = comparefunc;
- comparefunc = args;
- if (comparefunc != NULL) {
- /* Test the comparison function for obvious errors */
- (void) cmp((ANY *)&self->ob_item[0], (ANY *)&self->ob_item[1]);
- if (PyErr_Occurred()) {
- comparefunc = save_comparefunc;
- return NULL;
- }
- }
- qsort((char *)self->ob_item,
- (int) self->ob_size, sizeof(PyObject *), cmp);
- comparefunc = save_comparefunc;
- if (PyErr_Occurred())
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- #endif
-
- static PyObject *
- listreverse(self, args)
- PyListObject *self;
- PyObject *args;
- {
- register PyObject **p, **q;
- register PyObject *tmp;
-
- if (args != NULL) {
- PyErr_BadArgument();
- return NULL;
- }
-
- if (self->ob_size > 1) {
- for (p = self->ob_item, q = self->ob_item + self->ob_size - 1;
- p < q; p++, q--) {
- tmp = *p;
- *p = *q;
- *q = tmp;
- }
- }
-
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- int
- PyList_Reverse(v)
- PyObject *v;
- {
- if (v == NULL || !PyList_Check(v)) {
- PyErr_BadInternalCall();
- return -1;
- }
- v = listreverse((PyListObject *)v, (PyObject *)NULL);
- if (v == NULL)
- return -1;
- Py_DECREF(v);
- return 0;
- }
-
- int
- PyList_Sort(v)
- PyObject *v;
- {
- if (v == NULL || !PyList_Check(v)) {
- PyErr_BadInternalCall();
- return -1;
- }
- v = listsort((PyListObject *)v, (PyObject *)NULL);
- if (v == NULL)
- return -1;
- Py_DECREF(v);
- return 0;
- }
-
- PyObject *
- PyList_AsTuple(v)
- PyObject *v;
- {
- PyObject *w;
- PyObject **p;
- int n;
- if (v == NULL || !PyList_Check(v)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- n = ((PyListObject *)v)->ob_size;
- w = PyTuple_New(n);
- if (w == NULL)
- return NULL;
- p = ((PyTupleObject *)w)->ob_item;
- memcpy((ANY *)p,
- (ANY *)((PyListObject *)v)->ob_item,
- n*sizeof(PyObject *));
- while (--n >= 0) {
- Py_INCREF(*p);
- p++;
- }
- return w;
- }
-
- static PyObject *
- listindex(self, args)
- PyListObject *self;
- PyObject *args;
- {
- int i;
-
- if (args == NULL) {
- PyErr_BadArgument();
- return NULL;
- }
- for (i = 0; i < self->ob_size; i++) {
- if (PyObject_Compare(self->ob_item[i], args) == 0)
- return PyInt_FromLong((long)i);
- if (PyErr_Occurred())
- return NULL;
- }
- PyErr_SetString(PyExc_ValueError, "list.index(x): x not in list");
- return NULL;
- }
-
- static PyObject *
- listcount(self, args)
- PyListObject *self;
- PyObject *args;
- {
- int count = 0;
- int i;
-
- if (args == NULL) {
- PyErr_BadArgument();
- return NULL;
- }
- for (i = 0; i < self->ob_size; i++) {
- if (PyObject_Compare(self->ob_item[i], args) == 0)
- count++;
- if (PyErr_Occurred())
- return NULL;
- }
- return PyInt_FromLong((long)count);
- }
-
- static PyObject *
- listremove(self, args)
- PyListObject *self;
- PyObject *args;
- {
- int i;
-
- if (args == NULL) {
- PyErr_BadArgument();
- return NULL;
- }
- for (i = 0; i < self->ob_size; i++) {
- if (PyObject_Compare(self->ob_item[i], args) == 0) {
- if (list_ass_slice(self, i, i+1,
- (PyObject *)NULL) != 0)
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
- }
- if (PyErr_Occurred())
- return NULL;
- }
- PyErr_SetString(PyExc_ValueError, "list.remove(x): x not in list");
- return NULL;
- }
-
- static PyMethodDef list_methods[] = {
- {"append", (PyCFunction)listappend},
- {"insert", (PyCFunction)listinsert},
- {"remove", (PyCFunction)listremove},
- {"index", (PyCFunction)listindex},
- {"count", (PyCFunction)listcount},
- {"reverse", (PyCFunction)listreverse},
- {"sort", (PyCFunction)listsort, 0},
- {NULL, NULL} /* sentinel */
- };
-
- static PyObject *
- list_getattr(f, name)
- PyListObject *f;
- char *name;
- {
- return Py_FindMethod(list_methods, (PyObject *)f, name);
- }
-
- static PySequenceMethods list_as_sequence = {
- (inquiry)list_length, /*sq_length*/
- (binaryfunc)list_concat, /*sq_concat*/
- (intargfunc)list_repeat, /*sq_repeat*/
- (intargfunc)list_item, /*sq_item*/
- (intintargfunc)list_slice, /*sq_slice*/
- (intobjargproc)list_ass_item, /*sq_ass_item*/
- (intintobjargproc)list_ass_slice, /*sq_ass_slice*/
- };
-
- PyTypeObject PyList_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "list",
- sizeof(PyListObject),
- 0,
- (destructor)list_dealloc, /*tp_dealloc*/
- (printfunc)list_print, /*tp_print*/
- (getattrfunc)list_getattr, /*tp_getattr*/
- 0, /*tp_setattr*/
- (cmpfunc)list_compare, /*tp_compare*/
- (reprfunc)list_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- &list_as_sequence, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- };
-